AddCSLuaFile("shared.lua")
AddCSLuaFile("cl_init.lua")

resource.AddFile("materials/vgui/entities/zpm_spawner.vmt")
resource.AddFile("materials/vgui/entities/zpm_spawner.vtf")

include("shared.lua")

ENT.LastZPM = nil
ENT.Spinning = false
ENT.count = 0;
ENT.Player = nil;
ENT.ZPMlist = {};

--################# What version is installed? @aVoN   (RD3 or RD2)
local RD; -- QuickIndex
local IsThree;
local function RD3()
	if(IsThree ~= nil) then return IsThree end;
	if(CAF and CAF.GetAddon("Resource Distribution")) then
		IsThree = true;
		RD = CAF.GetAddon("Resource Distribution");
		return true;
	end
	IsThree = false;
	return false;
end

function ENT:Initialize(ply)
	if file.Exists("../models/magnusson_teleporter.mdl") then
		self.Entity:SetModel("models/magnusson_teleporter.mdl")
	else
		self.Entity:SetModel("models/zpmnusson_teleporter.mdl")
	end
	self.Max = StarGate.CFG:Get("ZPM_Spawner","MaxZPM",2)   --Now set in the Config File for this addon, lua/autorun/MckaysPack.lua
	self.countdown = 0;   --Really this counts upwards ... but its the time UNTIL the zpm is fully created
	self.Entity:PhysicsInit(SOLID_VPHYSICS)
	self.Entity:SetSolid(SOLID_VPHYSICS)
	self.Canmake = true;
	self.RequiredEnergy = 1000000000;			--This is the amount of energy needed to spawn the ZPM. 1,000,000,000
	self:AddResource("energy",self.RequiredEnergy);
	if RD3() then
		self.RequiredWater = 1000000;			--This is the amount of water needed to spawn the ZPM. 1,000,000
		self:AddResource("water",self.RequiredWater);
		self.RequiredCoolant = 1;
		self:CreateWireOutputs("Ready","Energy %","Water %","ZPM's Remaining");
	else
		self.RequiredCoolant = 1000000;			--This is the amount of coolant needed to spawn the ZPM. 1,000,000
		self:AddResource("coolant",self.RequiredCoolant);
		self.RequiredWater = 1;
		self:CreateWireOutputs("Ready","Energy %","Coolant %","ZPM's Remaining");
	end
	self:CreateWireInputs("Make ZPM", "Destroy");
	util.PrecacheModel("models/magnusson_device.mdl")
	local phy = self.Entity:GetPhysicsObject()
	if phy:IsValid() then phy:EnableMotion(false) end
end

function ENT:SpawnFunction(ply,tr)
	--if !tr.HitWorld then return end     --This is why i can't spawn it on a prop!
	if(tr.Entity and tr.Entity:IsPlayer()) then return false end;
	local sbs = ents.Create("zpm_spawner")
	sbs:SetPos(tr.HitPos)
	sbs:Spawn()
	self.Player = ply;
	return sbs
end

function ENT:ShowOutput(energy,water)
	local OverlayText="";
	local add = "(Disabled)";
	if(self.count < self.Max) then add = "(Active)" end;
	if(not self.active && self.count < self.Max) then add = "(Standby)" end;
	if(self.Making) then add = "(Making ZPM!)" end;
	self.Entity:SetNetworkedString("STATUS", add)
	self.Entity:SetNetworkedString("AMMOUNT", "ZPM's Left: "..self.Max-self.count)
	self.Entity:SetNetworkedString("ENERGY", "Energy: "..math.floor(energy))
	if RD3() then
		self.Entity:SetNetworkedString("WATER", "Water: "..math.floor(water))
	else
		self.Entity:SetNetworkedString("WATER", "Coolant: "..math.floor(water))
	end
end

function ENT:Think()
	local ammount = self.Max-self.count;
	local Energy = self:GetResource("energy") or 0;
	local Water = self:GetResource("water") or 0;
	local Coolant = self:GetResource("coolant") or 0;
	local percentE = (Energy/self.RequiredEnergy)*100;
	if RD3() then
		local percentW = (Water/self.RequiredWater)*100;
		self:ShowOutput(percentE,percentW);
		self:SetWire("Water %",percentW);
	else
		local percentC = (Coolant/self.RequiredCoolant)*100;
		self:ShowOutput(percentE,percentC);
		self:SetWire("Coolant %",percentC);
	end
	
	self:SetWire("Ready",self.active);
	self:SetWire("Energy %",percentE);
	self:SetWire("ZPM's Remaining", ammount);
	
	self.countonce = self.countonce or false; --if true then we have already counted to 10
	
	--Cant slow down think time, as spinning becomes out of sync. :(
	
	if (self.Making && not self.countonce) then
		self.countdown = self.countdown+1
		self:ConsumeResource("energy",(self.RequiredEnergy/10))
		if RD3() then
			self:ConsumeResource("water",(self.RequiredWater/10))
		else
			self:ConsumeResource("coolant",(self.RequiredCoolant/10))
		end
		if(self.countdown >= 10) then
			self.countonce = true;
			self.countdown = 0;
		end
	end
	
	if (Energy >= self.RequiredEnergy && (Water >= self.RequiredWater || Coolant >= self.RequiredCoolant)) then
		self.active = true;
		if (not self.Making && ammount ~= 0) then
			if file.Exists("../models/magnusson_teleporter.mdl") then
				self.Entity:SetModel("models/magnusson_teleporter.mdl")
			else
				self.Entity:SetModel("models/zpmnusson_teleporter.mdl")
			end
		end
	else
		self.active = false;
		if (not self.Making) then
			if file.Exists("../models/magnusson_teleporter_off.mdl") then
				self.Entity:SetModel("models/magnusson_teleporter_off.mdl")
			else
				self.Entity:SetModel("models/zpmnusson_teleporter_off.mdl")
			end
		end
	end
	
	if self.Spinning then return end;
	if (self.active && self.Canmake && self.MakeZPM) then
		self.Making = true
		if(not self.Canmake) then return end;
		self.Canmake = false
		local sAng = self.Entity:GetAngles()
		if !(self.LastZPM != nil && self.LastZPM:IsValid()) || (self.LastZPM && self.LastZPM:IsValid() && self.LastZPM:GetPos():Distance(self:ZPMPos()) > 20) then
			if (self.count >= self.Max) then
				if(not self.done) then
					self.Making = false
					self.Owner:PrintMessage(HUD_PRINTTALK, "Error: ZPM Spawn Limit!" ); -- DIFFERENT FROM aVoN's Stargate config value!!
					self.Owner:PrintMessage(HUD_PRINTTALK, "Please Create Another ZPM Spawner!" );
					--@Meeces2911 Will change this, might make a popup display, display remaining ZPM's and then have spawner EXPLODE! when max is reached .. ?
					if file.Exists("../models/magnusson_teleporter_off.mdl") then
						self.Entity:SetModel("models/magnusson_teleporter_off.mdl")
					else
						self.Entity:SetModel("models/zpmnusson_teleporter_off.mdl")
					end
					self.done = true;
				end
			else
				self.Spinning = true
				local spSeq = self.Entity:LookupSequence("spinup")
				self.Entity:ResetSequence(spSeq)
				timer.Simple(7,self.SpawnZPM,self.Entity)
			end
		else
			self.Canmake = true
			self.Spinning = false
			self.Making = false
		end
	end
	--sanity check, can we make - zpms ? i think NOT
	if self.count > self.Max then
		self.count = self.Max;
	end
end

function ENT:SpawnZPM(ply)
	if !(self.Entity != nil && self.Entity:IsValid()) then return end
	if self.count >= self.Max then return end
	local zpm 
	if (StarGate.CFG:Get("ZPM_Spawner","ZPMType",2) == 2) then
		zpm = ents.Create("Zero_Point_Module_Mk2"); -- Spawn MK2 ZPMs or Normal !?
	else
		zpm = ents.Create("Zero_Point_Module"); -- Spawn MK2 ZPMs or Normal !?
	end
	zpm:SetPos(self:ZPMPos())
	local sA = self.Entity:GetAngles()
	zpm:SetAngles(sA)
	zpm:Spawn()
	
	table.insert(self.ZPMlist,zpm);
	
	-- weld it on in case we have a moving zpm spawner ( on a vehicle :D )
	local const = constraint.Weld(self.Entity,zpm,0,0,2000,false)
	
	self.LastZPM = zpm
	self.Spinning = false
	self.count = self.count+1;
	self.Canmake = true
	self.Making = false
	self.MakeZPM = false;
	self.countonce = false;
end

function ENT:ZPMPos()
	local sAng = self.Entity:GetAngles()
	return self.Entity:GetPos() - sAng:Right() * 4 + sAng:Up() * 48
end

function ENT:OnRemove()
--@meeces2911 GAH, when i find out how to stop the sound and effects that will go here!!
	--self.SetPlaybackRate(self.Entity,0);
	--local spSeq = self.Entity:LookupSequence("idle")
	--self.Entity:SetSequence(spSeq)
	--self.ResetSequenceInfo(self.Entity);
	--self.Entity:StopSound();
end

function ENT:Use()
	if self.active then
		self.MakeZPM = true;
	end
end

function ENT:TriggerInput(name,value)
	if (name == "Make ZPM") then
		if (value == 1) then
			self.MakeZPM = true;
		else
			self.MakeZPM = false;
		end
	end
	
	if (name == "Destroy") then
		if (value == 1) then
			--Blow up ZPM spawner, and all ZPM's attached to it!!!
			for k,v in pairs(self.ZPMlist) do
				if v:IsValid() then
					if v:GetClass():lower() == "zero_point_module_mk2" then
						tryblowup(k,v)
						self.count = self.count-1;
					end
				end
			end
			
			local shake = ents.Create("env_shake")
			shake:SetKeyValue("amplitude", 2.5)
			shake:SetKeyValue("duration", 7)
			shake:SetKeyValue("radius", 163.84*(StarGate.CFG:Get("ZPM_Mk2","ExplosionRadius",6)*5)) 
			shake:SetKeyValue("frequency", 2.3*3)
			shake:SetPos(self.Entity:GetPos())
			shake:Spawn()
			shake:Fire("StartShake","","0.6")
			shake:Fire("kill","","8")
			
			timer.Create( "Boom_Time"..self.Entity:EntIndex(), 5, 0, function() 
				local nuke = ents.Create("gate_nuke")
				nuke:Setup(self:GetPos(), StarGate.CFG:Get("ZPM_Mk2","ExplosionRadius",6))	
				nuke:Spawn()
				nuke:Activate()
				timer.Destroy("Boom_Time"..self.Entity:EntIndex());
				self.Remove(self.Entity);
			end );
			
		else
			timer.Destroy("Boom_Time"..self.Entity:EntIndex());
			for k,v in pairs(self.ZPMlist) do
				timer.Simple(k+1,v.TriggerInput,v,"Overload",0);
				self.count = self.count+1;
			end
		end
	end
end

function tryblowup(k,v)
	timer.Simple(k+1,v.TriggerInput,v,"Overload",1);
end